﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FinanSoft.Utilities;
using FinanSoft.Entities;
using System.Xml;
using FinanSoft.BusinessLayer;
using System.Data.SqlClient;

namespace FinanSoft.DataLayer
{
    class OpenDocumentDataManager
    {
        #region Singleton

        private OpenDocumentDataManager()
        {}
        /// <summary>
        /// Unica Instancia de esa clase
        /// </suammary>
        private static OpenDocumentDataManager _instance;

        /// <summary>
        /// Metodo para implementar el patrón singleton
        /// </summary>
        /// <returns>Instancia única de la clase</returns>
        public static OpenDocumentDataManager GetInstance() 
        {
            if (_instance == null)
                _instance = new OpenDocumentDataManager();
            return _instance;
        }
        #endregion 

        #region Métodos
               
        /// <summary>
        /// Método que se encarga de leer las lista de tipos cuentas asignadas como un tipo de
        /// cuenta especial de la base de datos y mandar a parsear el xml que el stored procedure 
        /// devuelve para convertirlo en un objeto de tipo SpecialAccount
        /// </summary>
        /// <returns>Retorna el objeto cuentas especiales</returns>
        public OpenDocument[] GetOpenDoc(int idCtaAux)
        {

            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_OPEN_DOCS;
                SqlParameter[] parameters = new SqlParameter[1];
                parameters[0] = new SqlParameter(Constants.SP_PARAM_OPEN_DOCS_CTA_AUX_ID, idCtaAux);
                Console.WriteLine(parameters[0]);
                Console.WriteLine(Constants.SP_PARAM_OPEN_DOCS_CTA_AUX_ID + " *** " + idCtaAux);
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                if (result.HasRows)
                {
                    result.Read();
                    string xmlString = result.GetString(0);
                    dataHelper.CloseReader();
                    xmlString = Constants.ROOT_NODE_BEGINNING + xmlString + Constants.ROOT_NODE_ENDING;

                    // Se crea un documento XML con el string recibido
                    XmlDocument xmlOpenDoc = new XmlDocument();

                    xmlOpenDoc.LoadXml(xmlString);
                    return BuildxmlOpenDoc(xmlOpenDoc);
                }
                else
                    return new OpenDocument[0];
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// Método que recibe el documento xml a parsear para convertirlo en un SpecialAccount
        /// </summary>
        /// <param name="xmlPeriod">es el string xml a parsear</param>
        /// <returns>retorna un arreglo de todos los tipos de cuentas especiales</returns>
        public OpenDocument[] BuildxmlOpenDoc(XmlDocument xmlOpenDoc)
        {
            
            // Aquí llamo a la clase de la base de datos que me regresa el string
            //String xmlString = "";
            XmlNodeList nodeChildren = xmlOpenDoc.FirstChild.ChildNodes;

            OpenDocument[] arrayOpenDoc = new OpenDocument[nodeChildren.Count];
            

            // Por cada nodo principal
            int periodIndex = 0;
            
            foreach (XmlNode node in nodeChildren)
            {
                XmlNode nodeDocType = node[Constants.OPEN_DOC_NODE_NAME];
                
                OpenDocument OpenDoc = new OpenDocument();

                OpenDoc.idDocumento = System.Convert.ToInt32(node.Attributes.GetNamedItem(Constants.TAG_NAME_OPEN_DOCS_ID).Value);
                OpenDoc.codigoDocumento = System.Convert.ToInt32(node.Attributes.GetNamedItem(Constants.TAG_NAME_OPEN_DOCS_COD).Value);
                OpenDoc.fechaVencimiento = node.Attributes.GetNamedItem(Constants.TAG_NAME_OPEN_DOCS_EXP_DATE).Value;
                OpenDoc.monto = System.Convert.ToDouble(node.Attributes.GetNamedItem(Constants.TAG_NAME_OPEN_DOCS_AMOUNT).Value.Replace(".", ","));
                OpenDoc.Currency = MoneyManager.GetInstance().GetCurrency(System.Convert.ToInt32(node.Attributes.GetNamedItem(Constants.TAG_NAME_OPEN_DOCS_CURRENCY).Value));
                OpenDoc.tipoDocumento = nodeDocType.Attributes.GetNamedItem(Constants.TAG_NAME_OPEN_DOCS_TYPE).Value;
                
                arrayOpenDoc[periodIndex] = OpenDoc;
                periodIndex++;

            }
            
            return arrayOpenDoc;
        }

        /// <summary>
        /// Cambia el estado de los documentos a cancelados para que ya no aparezcan como facturas pendientes y además
        /// registra las transacciones hechas
        /// </summary>
        /// <param name="openDocs"></param>
        /// <returns></returns>
        public bool CancelDocuments(List<OpenDocument> openDocs, Account bankingAccount, int billOwnerCode)
        {
            foreach (OpenDocument openDoc in openDocs)
            {
                try
                {
                    AppConfigReader appConfig = AppConfigReader.GetInstance();
                    string spName = Constants.SP_NAME_REGISTER_TRANSFER;
                    SqlParameter[] parameters = {
                        new SqlParameter(Constants.SP_PARAM_REGISTER_TRANSFER_DOCUMENT_ID, openDoc.idDocumento),
                        new SqlParameter(Constants.SP_PARAM_REGISTER_TRANSFER_ACCOUNT_ID, bankingAccount.AccountID),
                        new SqlParameter(Constants.SP_PARAM_REGISTER_TRANSFER_LOCAL_AMOUNT, openDoc.monto * openDoc.Currency.ToLocalCurrency)};
                    SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                    dataHelper.ExecuteNoResultStoredProcedure(spName, parameters);
                }
                catch (Exception e)
                {
                    return false;
                }
            }
            return true;
        }
        
        #endregion
    }
}
